import java.util.*;

/*
 *  @author  Alpesh Mistry  <apm1dec@gmail.com>
 *  @author  Ankur Kothari  <a.kothari711@gmail.com>
 *  @author  Elman Mansimov <elman.mansimov@gmail.com>
 *  @author  Michelle Pan   <panmiche@gmail.com>
 *  @version 1.0
 *  @since   2012-03-03
 */

public class Directory extends SystemItem {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8805884756261430005L;
	private Hashtable<String, SystemItem> contents; //contents of Directory
	
	/**
	 * Initialize a directory object with an empty Hashtable to hold
	 * the files and directories it contains.
	 * @param n String which is the name of Directory.
	 * @param d Directory which we are initializing.
	 */
	public Directory(String n, Directory d) {
		super(n, d);
		contents = new Hashtable<String, SystemItem>();
		addPeriods();
	}
	
	/**
	 * Helper function of constructor of Directory object.
	 * It adds "." as itself and ".." as parent (if exists) 
	 * to directory's contents. Used in command cd.
	 */
	private void addPeriods() {

		addItem(".", this);
		if (this.getParent() != null)
			addItem("..", this.getParent());
		else
			addItem("..", this);
	}
	
	/**
	 * Add item to the directory's contents.
	 * @param n String which is the name of item
	 * @param item SystemItem which can be either File or Directory
	 */
	public void addItem(String n, SystemItem item) {
		contents.put(n, item);
	}
	
	/**
	 * 
	 * Remove item from directory's contents.
	 * 
	 * @param key String which is the name of item
	 */
	public void removeItem(String key) {
		contents.get(key).setParent(null);
		contents.remove(key);
	}
	
	/**
	 * Return contents of directory.
	 * @return Hashtable which is contents of directory
	 */
	public Hashtable<String, SystemItem> getContents() {
		
		Hashtable<String, SystemItem> temp = contents;

		if (temp == null)
			temp = tempContents();
		else {
			temp.put(".", this);
			if (this.getParent() != null)
				temp.put("..", this.getParent());
		}

		return temp;
	}
	
	public Hashtable<String, SystemItem> tempContents() {
		
		Hashtable<String, SystemItem> newTemp = new Hashtable<String, SystemItem>();
		newTemp.put(".", this);
		if (this.getParent() != null)
			newTemp.put("..", this.getParent());
		else
			newTemp.put("..", this);

		return newTemp;
	}
	
	/**
	 * Print contents of directory.
	 */
	public String printContents(boolean recurse, String path) {

		String keyNames = path + ":\n";
		String itemName = null;
		String recurseNames = "";
		String[] keys = (String[]) getContents().keySet().toArray(new String[0]);  
	    Arrays.sort(keys); 
	    for(String key : keys) {
			itemName = key;
			keyNames += itemName + "\n";
			if (recurse && !(itemName.equals("..") || itemName.equals(".")))
				try {

					recurseNames += ((Directory) getContents().get(itemName)).printContents(recurse, path + "/" + itemName);
				
				} catch (Exception e) {}
		}
		keyNames = keyNames.replace("\n.\n", "\n");
		keyNames = keyNames.replace("\n..\n", "\n");
		if (!recurseNames.equals(""))
			keyNames += "\n" + recurseNames;

		return keyNames;
	}

	@SuppressWarnings("unchecked")
	public void linkContents(Object newContents) {

		contents =  (Hashtable<String, SystemItem>) newContents;
	}

	public void nullifyLinks(){
		
		Iterator<SystemItem> itr = this.getLinksMade().iterator();
		SystemItem temp = null;

		while (itr.hasNext()) {

			temp = itr.next();
			temp.nullifyLinks();
			temp.linkContents(null);
		}
	}
	
	public Directory copy(Directory parentGiven){

		Directory itemDir = null;
		File itemFile = null;
		SystemItem tempItem = null;
		
		Directory tempCopy = new Directory(this.getName(), parentGiven); 
		if (this.getLink()) {
			tempCopy.linkContents(this.getContents()); 
		} else {
			Enumeration<SystemItem> itr = this.getContents().elements();
			while (itr.hasMoreElements()) {
				try {
					tempItem = itr.nextElement();
					itemDir = (Directory) tempItem;
					if (!(itemDir == this || itemDir == this.getParent()))
						tempCopy.addItem(itemDir.getName(), itemDir.copy(tempCopy));
				} catch (Exception e) {
					
					itemFile = (File) tempItem;
					tempCopy.addItem(itemFile.getName(), itemFile.copy(tempCopy));
				}
			}
		}
		return tempCopy;
	}

	@Override
	public Hashtable<String, SystemItem> getContentObject() {
		// TODO Auto-generated method stub
		return contents;
	}

	@Override
	public void eraseContents() {
		// TODO Auto-generated method stub
		contents = null;		
	}
}